x86: prevent access to HPET from Dom0
authorRoger Pau Monné <roger.pau@citrix.com>
Fri, 23 Jan 2015 14:16:18 +0000 (15:16 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 23 Jan 2015 14:16:18 +0000 (15:16 +0100)
Prevent Dom0 from accessing HPET MMIO region by adding the HPET mfn to the
list of forbiden memory regions (if ACPI_HPET_PAGE_PROTECT4 or
ACPI_HPET_PAGE_PROTECT64 flag is set) or to the list of read-only regions.

Also provide an option that prevents adding the HPET to the read-only memory
regions called ro-hpet, in case there are systems that put other stuff in
the HPET page.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Don't loop over iomem_deny_access() for consecutive MFNs.

Put new command line option's doc entry in right spot.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
docs/misc/xen-command-line.markdown
xen/arch/x86/acpi/boot.c
xen/arch/x86/domain_build.c
xen/arch/x86/hpet.c
xen/include/asm-x86/hpet.h

index a061aa41b6e278257997f7e4d82d681c46115b39..0fc75591598fd993a60f5a682a4640d27eadc782 100644 (file)
@@ -1119,6 +1119,14 @@ Specify the host reboot method.
 
 `pci` instructs Xen to reboot the host using PCI reset register (port CF9).
 
+### ro-hpet
+> `= <boolean>`
+
+> Default: `true`
+
+Map the HPET page as read only in Dom0. If disabled the page will be mapped
+with read and write permissions.
+
 ### sched
 > `= credit | credit2 | sedf | arinc653`
 
index 903830b3c1b7a41b6d2b87317c5dbfa5e6ecf327..9a8904bb869271944b6e87eb69a52ef82c5a5fe8 100644 (file)
@@ -309,6 +309,7 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
 
        hpet_address = hpet_tbl->address.address;
        hpet_blockid = hpet_tbl->sequence;
+       hpet_flags = hpet_tbl->flags;
        printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
               hpet_tbl->id, hpet_address);
 
index 2f9aaf95e60d7f46918289ac29894beac65b16f5..a561d7c5b0940236004b6ea7883c625f1f5a8ce8 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/bzimage.h> /* for bzimage_parse */
 #include <asm/io_apic.h>
 #include <asm/hap.h>
+#include <asm/hpet.h>
 
 #include <public/version.h>
 
@@ -134,6 +135,9 @@ boolean_param("dom0_shadow", opt_dom0_shadow);
 static char __initdata opt_dom0_ioports_disable[200] = "";
 string_param("dom0_ioports_disable", opt_dom0_ioports_disable);
 
+static bool_t __initdata ro_hpet = 1;
+boolean_param("ro-hpet", ro_hpet);
+
 /* Allow ring-3 access in long mode as guest cannot use ring 1 ... */
 #define BASE_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
 #define L1_PROT (BASE_PROT|_PAGE_GUEST_KERNEL)
@@ -1495,6 +1499,20 @@ int __init construct_dom0(
             rc |= iomem_deny_access(d, sfn, efn);
     }
 
+    /* Prevent access to HPET */
+    if ( hpet_address )
+    {
+        u8 prot_flags = hpet_flags & ACPI_HPET_PAGE_PROTECT_MASK;
+
+        mfn = paddr_to_pfn(hpet_address);
+        if ( prot_flags == ACPI_HPET_PAGE_PROTECT4 )
+            rc |= iomem_deny_access(d, mfn, mfn);
+        else if ( prot_flags == ACPI_HPET_PAGE_PROTECT64 )
+            rc |= iomem_deny_access(d, mfn, mfn + 15);
+        else if ( ro_hpet )
+            rc |= rangeset_add_singleton(mmio_ro_ranges, mfn);
+    }
+
     BUG_ON(rc != 0);
 
     if ( elf_check_broken(&elf) )
index 0b13f521eeb004e1e8d2fc434fcfb18a9614d093..7aa740f6fa433c09387ea7e81a1f13decc19bba7 100644 (file)
@@ -52,6 +52,7 @@ DEFINE_PER_CPU(struct hpet_event_channel *, cpu_bc_channel);
 
 unsigned long __initdata hpet_address;
 u8 __initdata hpet_blockid;
+u8 __initdata hpet_flags;
 
 /*
  * force_hpet_broadcast: by default legacy hpet broadcast will be stopped
index 875f1de42aa175f66b4f685656841384784bbc17..10c4a5694dbcba9f0f8ff993271e1a70a217b202 100644 (file)
@@ -52,6 +52,7 @@
 
 extern unsigned long hpet_address;
 extern u8 hpet_blockid;
+extern u8 hpet_flags;
 
 /*
  * Detect and initialise HPET hardware: return counter update frequency.